package cn.monkey.family.server.domain.uc.auth.wechat;

import cn.monkey.family.data.Result;
import cn.monkey.family.data.Results;
import cn.monkey.family.data.uc.user.User;
import cn.monkey.family.data.uc.auth.wechat.WechatAuthorizationRespCode;
import cn.monkey.family.data.uc.auth.wechat.WechatAuthorizationResp;
import cn.monkey.family.data.uc.auth.wechat.WechatUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.client.RestClient;

import java.util.Objects;
import java.util.Optional;

public class RemoteWechatClient implements WechatClient {

    private static final Logger log = LoggerFactory.getLogger(RemoteWechatClient.class);

    final RestClient restClient;

    final WechatProperties wechatProperties;

    final WechatUserRepository wechatUserRepository;

    public RemoteWechatClient(RestClient restClient,
                              WechatProperties wechatProperties,
                              WechatUserRepository wechatUserRepository) {
        this.restClient = restClient;
        this.wechatProperties = wechatProperties;
        this.wechatUserRepository = wechatUserRepository;
    }

    @Override
    public Result<WechatUser> findOneByCode(User user,
                                            String appId,
                                            String code) {
        String serverConfigAppId = this.wechatProperties.getAppId();
        if (!Objects.equals(serverConfigAppId, appId)) {
            log.error("invalid appId:{}", appId);
            return Results.fail("INVALID_APP_ID");
        }
        WechatAuthorizationResp wechatAuthorizationResp = this.restClient.get()
                .uri("https://api.weixin.qq.com/sns/jscode2session?appid={appId}&secret={secret}&js_code={code}&grant_type=authorization_code",
                        appId, this.wechatProperties.getSecret(), code)
                .retrieve()
                .body(WechatAuthorizationResp.class);
        Integer errorCode;
        if (wechatAuthorizationResp == null || (errorCode = wechatAuthorizationResp.getErrorCode()) == null) {
            log.error("invalid wechat signInResp: {}", wechatAuthorizationResp);
            return Results.fail("INVALID_CODE");
        }
        WechatAuthorizationRespCode wechatCode = WechatAuthorizationRespCode.valueOf(errorCode);
        if (wechatCode == null) {
            log.error("can not find wechat code status for response errorCode: {}", errorCode);
            return Results.fail("WECHAT_SIGN_IN_FAIL");
        }
        if (wechatCode != WechatAuthorizationRespCode.SUCCESS) {
            return Results.fail(wechatCode.getMsg());
        }
        String openid = wechatAuthorizationResp.getOpenid();
        Optional<WechatUser> wechatUserOptional = this.wechatUserRepository.findOneByUidAndOpenidAndAppId(user.getId(), openid, appId);
        WechatUser wu = wechatUserOptional.orElseGet(() -> {
            WechatUser wechatUser = new WechatUser();
            wechatUser.setUid(user.getId());
            wechatUser.setOpenid(openid);
            wechatUser.setAppId(appId);
            return this.wechatUserRepository.save(wechatUser);
        });
        return Results.ok(wu);
    }
}
